

module user_tx_check #(
    parameter SOURCE_IP         = {8'd192, 8'd168, 8'd7, 8'd11}                                          
)
(
    input                       i_clk                                   ,
    input                       i_rst                                   ,
    input   [31: 0]             i_set_source_ip                         ,
    input                       i_set_source_valid                      ,
    input   [31: 0]             i_arp_info_ip0                          ,
    input   [31: 0]             i_arp_info_ip1                          ,   
    output                      o_arp_req                               ,
    output  [31:0]              o_arp_req_ip                            ,
    input                       s_axis_tvalid                           ,
    input   [7 : 0]             s_axis_tdata                            ,
    output                      s_axis_tready                           ,
    input                       s_axis_tlast                            ,
    input   [67: 0]             s_axis_tuser                            ,
    output                      m_axis_tvalid                           ,
    output  [7 : 0]             m_axis_tdata                            ,
    input                       m_axis_tready                           ,
    output                      m_axis_tlast                            ,
    output  [67: 0]             m_axis_tuser                            
);
    logic                       s_tx_axis_tvalid                        ;
    logic                       s_tx_axis_tready                        ;
    logic                       s_tx_axis_tready_delay                  ;
    logic                       s_tx_axis_tlast                         ;
    logic   [67: 0]             s_tx_axis_tuser                         ;
    logic   [15: 0]             tx_len                                  ;
    logic   [23: 0]             arp_idle_cnt                            ;
    logic   [15: 0]             rd_cnt                                  ;
    logic                       arp_req                                 ;
    logic   [31: 0]             arp_req_ip                              ;  
    logic                       arp_tri                                 ;
    logic   [31: 0]             set_source_ip                           ;
    logic                       tx_arp_access                           ;
    logic                       fifo_wren                               ;
    logic   [7 : 0]             fifo_wrdata                             ;   
    logic                       fifo_rden                               ;
    logic   [7 : 0]             fifo_rddata                             ;
    logic                       fifo_full                               ;
    logic                       fifo_empty                              ;
    logic                       m_tx_axis_tvalid                        ;
    logic                       m_tx_axis_tlast                         ;
    logic   [67: 0]             m_tx_axis_tuser                         ; 

    // ila128_bit ila128_bit_check_tx(
    //     .clk    ( i_clk),
    //     .probe0 ( {s_axis_tvalid,s_axis_tdata,s_axis_tready,s_axis_tlast,s_axis_tuser[7:0],
    //     rd_cnt,fifo_wren,fifo_rden,fifo_empty,tx_arp_access,i_arp_info_ip0,i_arp_info_ip1,
    //     m_axis_tvalid,m_axis_tready,m_axis_tlast,s_axis_tuser[7:0]
    //     })

    // );
    

    assign fifo_rden = m_tx_axis_tvalid;
    assign s_axis_tready = s_tx_axis_tready;
    assign o_arp_req = arp_tri;
    assign o_arp_req_ip = arp_req_ip;
    assign m_axis_tvalid = m_tx_axis_tvalid;
    assign m_axis_tdata = fifo_rddata;
    assign m_axis_tlast = m_tx_axis_tlast;
    assign m_axis_tuser = m_tx_axis_tuser;
      
    always_ff @(posedge i_clk) begin
        if(i_rst) 
            set_source_ip <= SOURCE_IP;
        else if(i_set_source_valid)
            set_source_ip <= i_set_source_ip;
        else    
            set_source_ip <= set_source_ip;
    end

    sfifo_8x1024 sfifo_8x1024_inst (
        .clk                    ( i_clk                     ),      
        .din                    ( fifo_wrdata               ),      
        .wr_en                  ( fifo_wren                 ),  
        .rd_en                  ( fifo_rden                 ),  
        .dout                   ( fifo_rddata               ),    
        .full                   ( fifo_full                 ),   
        .empty                  ( fifo_empty                )  
    );
    
    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            fifo_wren <= 0;
        else if(s_axis_tvalid & s_axis_tready & (s_axis_tuser[47:24] == set_source_ip[31:8]))
            fifo_wren <= 1;
        else  
            fifo_wren <= 0;
    end

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            fifo_wrdata <= 0;
        else 
            fifo_wrdata <= s_axis_tdata;
    end

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            tx_len <= 0;
        else if(s_axis_tvalid & s_axis_tready)
            tx_len <= s_axis_tuser[15:0];
        else  
            tx_len <= tx_len;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) begin
            s_tx_axis_tvalid <= 0;                 
            s_tx_axis_tlast <= 0;        
            s_tx_axis_tuser <= 0;        
        end
        else begin
            s_tx_axis_tvalid <= s_axis_tvalid;                 
            s_tx_axis_tlast <= s_axis_tlast;        
            s_tx_axis_tuser <= s_axis_tuser;    
        end
    end   

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            s_tx_axis_tready <= 0;
        else if(fifo_wren & s_axis_tlast)
            s_tx_axis_tready <= 0;
        else if(fifo_empty & !fifo_rden & m_axis_tready)
            s_tx_axis_tready <= 1;
        else  
            s_tx_axis_tready <= s_tx_axis_tready;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            s_tx_axis_tready_delay <= 0;
        else 
            s_tx_axis_tready_delay <= s_tx_axis_tready;
    end  


    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            tx_arp_access <= 0;
        else if(!fifo_empty && (arp_req_ip == i_arp_info_ip0 || arp_req_ip == i_arp_info_ip1))
            tx_arp_access <= 1;
        else if(!fifo_empty)
            tx_arp_access <= 0;
        else  
            tx_arp_access <= tx_arp_access;
    end  

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            arp_req <= 0;
        else if(!fifo_empty && arp_req_ip != i_arp_info_ip0 && arp_req_ip != i_arp_info_ip1) 
            arp_req <= 1;
        else 
            arp_req <= 0;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst)
            arp_req_ip <= 0;
        else  
            arp_req_ip <= s_axis_tuser[47:16];
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            arp_idle_cnt <= 0;
        else if(arp_req)
            arp_idle_cnt <= arp_idle_cnt + 1;
        else 
            arp_idle_cnt <= 0;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            arp_tri <= 0;
        else if(arp_idle_cnt == 1)
            arp_tri <= 1;
        else 
            arp_tri <= 0;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            m_tx_axis_tvalid <= 0;
        else if(m_tx_axis_tvalid & m_tx_axis_tlast)
            m_tx_axis_tvalid <= 0;
        else if(tx_arp_access && !fifo_empty && m_axis_tready)
            m_tx_axis_tvalid <= 1;
        else  
            m_tx_axis_tvalid <= m_tx_axis_tvalid;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            m_tx_axis_tlast <= 0;
        else if(tx_len == 1 && m_tx_axis_tlast == 1)
            m_tx_axis_tlast <= 0;
        else if(tx_len == 1 && tx_arp_access && !fifo_empty && m_axis_tready)
            m_tx_axis_tlast <= 1;
        else if(tx_len == 2 && m_tx_axis_tvalid == 1)
            m_tx_axis_tlast <= 1;
        else if(tx_len >= 3 && rd_cnt == tx_len- 2)
            m_tx_axis_tlast <= 1;
        else  
            m_tx_axis_tlast <= 0;
    end 

    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            m_tx_axis_tuser <= 0;
        else if(tx_arp_access)
            m_tx_axis_tuser <= s_axis_tuser;
        else  
            m_tx_axis_tuser <= m_tx_axis_tuser;
    end 


    always_ff @( posedge i_clk ) begin
        if(i_rst) 
            rd_cnt <= 0;
        else if(fifo_rden & m_tx_axis_tlast)
            rd_cnt <= 0;
        else if(fifo_rden )
            rd_cnt <= rd_cnt + 1;
        else 
            rd_cnt <= rd_cnt;
    end 







endmodule